package com.open4cn.simulator.device;

import com.open4cn.simulator.core.connector.ConnectorModeEnum;
import com.open4cn.simulator.core.connector.IConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yinxiaopeng
 * @version 1.0.0
 * @company 致景科技
 * @department 飞梭BU/研发
 * @description
 * @Email yinxiaopeng@zj.tech
 * @date 2022-06-04 23:34
 */
public class ConnectorManager {
    private static Logger logger = LoggerFactory.getLogger(ConnectorManager.class);

    // k= 设备唯一标识
    private ConcurrentHashMap<String, IConnector> container = new ConcurrentHashMap<>();


    /**
     * 是否可允许
     * 检查端口冲突
     *
     * @param deviceId
     * @return
     */
    public boolean executable(String deviceId) {
        if (!exists(deviceId)) {
            return false;
        }
        IConnector connector = get(deviceId);
        if (ConnectorModeEnum.TCP_SERVER.equals(connector.getConnectorMode())) {
            Integer port = connector.getConnectAddress().getPort();
            for (IConnector v : container.values()) {
                if (ConnectorModeEnum.TCP_SERVER.equals(v.getConnectorMode())
                        && v.getConnectStatus().isConnected()
                        && port.equals(v.getConnectAddress().getPort())) {
                    return false;
                }
            }
        }
        if (ConnectorModeEnum.SERIAL_PORT.equals(connector.getConnectorMode())) {
            String comPort = connector.getConnectAddress().getComPort();
            for (IConnector v : container.values()) {
                if (ConnectorModeEnum.SERIAL_PORT.equals(v.getConnectorMode())
                        && v.getConnectStatus().isConnected()
                        && comPort.equals(v.getConnectAddress().getComPort())) {
                    return false;
                }
            }

        }
        return true;
    }


    public void put(String deviceId, IConnector connector) {
        if (exists(deviceId)) {
            logger.warn("{}设备connector已存在,即将覆盖", deviceId);
        }
        container.put(deviceId, connector);
    }


    public void remove(String deviceId) {
        if (exists(deviceId)) {
            IConnector connector = get(deviceId);
            if (connector.getConnectStatus().isClosed()) {
                container.remove(deviceId);
                return;
            }
            logger.warn("{}设备connector移除失败", deviceId);
        }
    }

    public IConnector get(String deviceId) {
        if (null != deviceId && deviceId.length() != 0) {
            return container.get(deviceId);
        }
        return null;
    }


    public String snapshot(String deviceId) {
        if (!exists(deviceId)) {
            return null;
        }
        IConnector connector = get(deviceId);
        StringBuilder builder = new StringBuilder();
        builder.append(deviceId)
                .append(":")
                .append(connector.getConnectorMode().name())
                .append(":")
                .append(connector.getConnectStatus().getStatus().name())
                .append(":");
        if (ConnectorModeEnum.TCP_SERVER.equals(connector.getConnectorMode())) {
            builder.append(connector.getConnectAddress().getPort());
        }
        if (ConnectorModeEnum.TCP_CLIENT.equals(connector.getConnectorMode())) {
            builder.append(connector.getConnectAddress().getHost());
            builder.append(":");
            builder.append(connector.getConnectAddress().getPort());
        }
        if (ConnectorModeEnum.SERIAL_PORT.equals(connector.getConnectorMode())) {
            builder.append(connector.getConnectAddress().getComPort());
            builder.append(":");
            builder.append(connector.getConnectAddress().getBaudRate());
        }
        return builder.toString();
    }

    public boolean exists(String deviceId) {
        return null != get(deviceId);
    }


    /**
     * --------------------------------------------
     **/

    private ConnectorManager() {
    }

    private static class HolderClass {
        private static final ConnectorManager instance = new ConnectorManager();
    }

    public static ConnectorManager getInstance() {
        return ConnectorManager.HolderClass.instance;
    }
}
